package com.freewater.parking.application;

import com.freewater.parking.infrastructure.event.DomainEventDispatcher;
import com.freewater.parking.infrastructure.event.SimpleEventQueue;
import com.freewater.parking.domain.blacklist.AddedToBlackListEvent;
import com.freewater.parking.domain.blacklist.BlackList;
import com.freewater.parking.domain.blacklist.BlackListRepository;
import com.freewater.parking.domain.blacklist.RemovedFromBlackListEvent;
import com.freewater.parking.domain.common.DomainEvent;
import com.freewater.parking.domain.common.EventQueue;
import com.freewater.parking.domain.common.PlateNumber;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;


@Slf4j
@Service
@Transactional
@AllArgsConstructor
public class BlackListAppServiceImpl implements BlackListAppService {

    private BlackListRepository blackListRepository;
    private DomainEventDispatcher eventDispatcher;

    @Override
    public void addPlateNumber(PlateNumber plateNumber) {
        boolean exist = this.blackListRepository.existsById(plateNumber);
        if (exist) {
            return;
        }
        BlackList blackList = new BlackList(plateNumber);
        this.blackListRepository.save(blackList);
        EventQueue queue = new SimpleEventQueue();
        queue.enqueue(new AddedToBlackListEvent(plateNumber, LocalDateTime.now()));
        dispatchEvents(queue);
    }

    @Override
    public void removePlateNumber(PlateNumber plateNumber) {
        boolean exist = this.blackListRepository.existsById(plateNumber);
        if (!exist) {
            return;
        }
        this.blackListRepository.delete(new BlackList(plateNumber));
        EventQueue queue = new SimpleEventQueue();
        queue.enqueue(new RemovedFromBlackListEvent(plateNumber, LocalDateTime.now()));
        dispatchEvents(queue);
    }

    @Override
    public boolean existPlateNumber(PlateNumber plateNumber) {
        return this.blackListRepository.existsById(plateNumber);
    }

    private void dispatchEvents(EventQueue queue) {
        for (DomainEvent domainEvent : queue.queue()) {
            eventDispatcher.dispatch(domainEvent);
        }
        queue.clear();
    }
}
